package com.sayai.work.tools.easyxml.demo;


import java.io.File;
import java.util.*;

import com.alibaba.excel.EasyExcel;
import com.sayai.work.tools.easyxml.demo.bank.BBJImp;
import com.sayai.work.tools.easyxml.demo.bank.BKMImp;
import com.sayai.work.tools.easyxml.demo.bank.BankConfig;
import org.apache.poi.util.StringUtil;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.tree.DefaultAttribute;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@EnableConfigurationProperties(BankConfig.class)
public class Dom4jDemo {

    @Autowired
    private BankConfig c;

    public void setBank(String bank) {
        this.bank = bank;
    }

    @Value("${bank.iswitch}")
    public String bank;


    private ArrayList<Leaf> elemList = new ArrayList<Leaf>();
    private Map<String, Integer> xpaths = new HashMap<String, Integer>();

    private ArrayList<ExcelBean> beanList = new ArrayList<ExcelBean>();

    private Map<String, Integer> doforcejob = new HashMap<String, Integer>();
    private Map<String, Integer> on = new HashMap<String, Integer>();
    private Map<String, Integer> doaction = new HashMap<String, Integer>();
    private Map<String, Integer> incond = new HashMap<String, Integer>();
    private Map<String, Integer> outcond = new HashMap<String, Integer>();
    private Map<String, Integer> shout = new HashMap<String, Integer>();
    private Map<String, Integer> variable = new HashMap<String, Integer>();
    private Map<String, Integer> job = new HashMap<String, Integer>();
    private Map<String, Integer> folder = new HashMap<String, Integer>();


    public Document getDocument(String filename) throws DocumentException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File(filename));

        getElementList(document.getRootElement());

        String outFileName = simpleWrite(filename);
        System.out.println("Excel'name is " + outFileName);

        return document;
    }

    private void printValidate() {

        /***
         *
         * key :/DEFTABLE/FOLDER/JOB/OUTCOND: 61045
         * key :/DEFTABLE: 1
         * key :/DEFTABLE/FOLDER/JOB/VARIABLE: 14930
         * key :/DEFTABLE/FOLDER: 1
         * key :/DEFTABLE/FOLDER/JOB/ON/DOACTION: 5
         * key :/DEFTABLE/FOLDER/JOB/INCOND: 29052
         * key :/DEFTABLE/FOLDER/JOB/SHOUT: 9554
         * key :/DEFTABLE/FOLDER/JOB/ON/DOFORCEJOB: 14930
         * key :/DEFTABLE/FOLDER/JOB: 14930
         * key :/DEFTABLE/FOLDER/JOB/ON: 14935
         */

        System.out.println("-----------doforcejob------------");
        doforcejob.forEach((k, v) -> System.out.println("key :" + k + ": " + v));

        // on
        System.out.println("-----------on------------\n");
        this.on.forEach((k, v) -> System.out.println("key :" + k + ": " + v));

        // doaction
        System.out.println("-----------doaction------------\n");
        this.doaction.forEach((k, v) -> System.out.println("key :" + k + ": " + v));

        // incond
        System.out.println("-----------incond------------\n");
        this.incond.forEach((k, v) -> System.out.println("key :" + k + ": " + v));

        // outcond
        System.out.println("-----------outcond------------\n");
        this.outcond.forEach((k, v) -> System.out.println("key :" + k + ": " + v));

        // shout
        System.out.println("-----------shout------------\n");
        this.shout.forEach((k, v) -> System.out.println("key :" + k + ": " + v));

        // variable
        System.out.println("-----------variable------------\n");
        this.variable.forEach((k, v) -> System.out.println("key :" + k + ": " + v));

        // job
        System.out.println("-----------job------------\n");
        this.job.forEach((k, v) -> System.out.println("key :" + k + ": " + v));

        // folder
        System.out.println("-----------folder------------\n");
        this.folder.forEach((k, v) -> System.out.println("key :" + k + ": " + v));


    }


    public String simpleWrite(String filename) {
        String fileName = filename + "_output_" + System.currentTimeMillis() + ".xls";
        // 这里 需要指定写用哪个class去读，然后写到第一个sheet，名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可

        // 根据用户传入字段 假设我们要忽略 date
        Set<String> excludeColumnFiledNames = new HashSet<String>();
        excludeColumnFiledNames.add("date");

        EasyExcel.write(fileName, ComplexHeadData.class).sheet("Sheet1").doWrite(beanList);
        return fileName;
    }


    private List<ExcelBean> data() {
        List<ExcelBean> list = new ArrayList<ExcelBean>();
        for (int i = 0; i < 10; i++) {
            ExcelBean data = new ExcelBean();
            data.setJobisn((1 + i) + "");
            data.setApplication("字符串" + i);
            data.setBim_desc("字符串");
            data.setCfr("");
            list.add(data);
        }
        return list;
    }


    private ExcelBean makeJobAndAtt(List list) {
        ExcelBean b = new ExcelBean();
        DefaultAttribute e = null;
        for (int i = 0; i < list.size(); i++) {
            e = (DefaultAttribute) list.get(i);
            switch (e.getName()) {
                case "APPLICATION": // Seq
                    b.setApplication(e.getText());
                    break;
                case "JOBISN": // Seq
                    b.setJobisn(e.getText());
                    break;
                case "MEMNAME": // TYPE
                    String memName = e.getText();
                    if (memName.startsWith("ctmfw")) {
                        b.setType("CTMFW");
                        b.setScriptname(memName.substring(5));
                    } else {
                        b.setType("C");
                        b.setScriptname(memName);
                    }
                    break;
                case "JOBNAME": // NODEID
                    b.setJobname(e.getText());
                    break;
                case "NODEID": // NODEID
                    b.setNodeid(e.getText());
                    break;
                case "RUN_AS": // OWNER
                    b.setRun_as(e.getText());
                    break;
                case "MEMLIB": // PATH
                    b.setMemlib(e.getText());
                    break;
                case "CMDLINE": // SCRIPT NAME
                    try {
                        if (this.bank.equals("BBJ")) {
                            String line = e.getText().replace("%%JOBNAME", b.getJobname().toUpperCase());
//                            if(line.indexOf(".pl") > 0)
//                            {
//                                String[] lines = line.split(".pl");
//                                b.setScriptname(lines[0] + ".pl");
//                                if(lines.length>1)
//                                    b.setParm1(lines[1]);
//                            }else if(line.indexOf(".py") > 0)
//                            {
//                                String[] lines = line.split(".py");
//                                b.setScriptname(lines[0] + ".py");
//                                if(lines.length>1)
//                                    b.setParm1(lines[1]);
//                            }
                            b.setScriptname(line);
                        } else if (this.bank.equals("BKM")) {
                            String[] cmdline = e.getText().split(" ");
                            if (cmdline.length == 2 && !cmdline[0].equals("ctmfw")) {
                                b.setParm1(cmdline[1]);
                            }
                        }
                    } catch (Exception ae) {
                        System.err.println(e.getText());
//                        ae.printStackTrace();
                    }

                    break;
                case "TIMEFROM": // FROMTIME
                    b.setTimefrom(e.getText());
                    break;
                case "TIMETO": // TOTIME
                    b.setTimeto(e.getText());
                    break;
                //MAXRERUN
                case "MAXRERUN": // MAXRERUN
                    String maxrerun = e.getText();
                    if (Integer.valueOf(maxrerun) == 0)
                        maxrerun = "";
                    else
                        maxrerun = (Integer.valueOf(maxrerun)).toString();
                    b.setMxrun(maxrerun);
                    break;
                //INTERVAL
                case "INTERVAL": // MAXRERUN
                    String v = e.getText();
                    if (v.endsWith("M"))
                        v = v.substring(0, v.length() - 1);
                    Integer in = Integer.valueOf(v);
                    if (in == 0)
                        v = "";
                    else
                        v = (Integer.valueOf(v)).toString();

                    b.setInterval(v);
                    break;
                case "DESCRIPTION": // SUPPORT /  FUNCTION
                    String description = e.getText();
                    String[] dess = description.split(". Function is: ");
                    String support = dess[0].substring("if error, call".length());
                    b.setDescription_error(support);
                    if (dess.length > 1) {
                        String function = dess[1];
                        b.setDescription_function(function);
                    }
                    break;
            }

            //System.out.println("name = " + e.getName() + ", value = " + e.getText());

        }
        return b;
    }


    private ExcelBean getSubNodeAtt(Element element, ExcelBean b) {
        List<Element> subs = element.elements();
        for (Element e : subs) {
            String subname = e.getName();
            List<Attribute> attrs = e.attributes();
            switch (subname) {
                case "INCOND": // PRE JOB
                    for (Attribute a : attrs) {
                        switch (a.getName()) {
                            case "NAME": // PRE JOB
                                try {
                                    String value = "";
//                                    c.getIswitch();
                                    if (this.bank.equals("BKM"))
                                        value = BKMImp.getInstance().makeIncond(a.getText());
                                    else if (this.bank.equals("BBJ"))
                                        value = BBJImp.getInstance().makeIncond(b, a.getText());


                                    String oldvalue = b.getIncond();
                                    if (oldvalue.length() > 0)
                                        b.setIncond(oldvalue + "\n" + value + ";");
                                    else if (value != null && value != "")
                                        b.setIncond(value + ";");
                                } catch (Exception ie) {
                                    ie.printStackTrace();
                                    System.err.println(a.getText());
                                }

                        }
                    }
                    break;
                case "ON": // NOTOK
                    for (Attribute a : attrs) {
                        switch (a.getName()) {
                            case "CODE": // PRE JOB
                                String value = a.getText();
                                if (value.indexOf("NOTOK") >= 0) {
                                    b.setDoaction_on_code("NOTOK");
                                    Element doaction = e.element("DOACTION");
                                    if (null != doaction)
                                        b.setDoaction_action(doaction.attribute("ACTION").getText());
                                }
                        }
                    }
                    break;

                case "SHOUT": // SHOUT
                    String when = "";
                    String time = "";
                    for (Attribute a : attrs) {
                        switch (a.getName()) {
                            case "WHEN": // PRE JOB
                                when = a.getText();
                                break;
                            case "TIME":
                                time = a.getText();
                                break;

                        }
                    }
                    if (when.equals("LATETIME"))
                        b.setShout_last_time(time);
                    if (when.equals("EXECTIME"))
                        b.setShout_exec_time(time);
                    break;
            }
        }

        return b;
    }

    private ExcelBean getAttFromJob(Element element) {
        ExcelBean b = makeJobAndAtt(element.attributes());
        b = getSubNodeAtt(element, b);
        return b;
    }

    /**
     * 获取节点所有属性值
     * <功能详细描述>
     *
     * @param element
     * @return
     * @see [类、类#方法、类#成员]
     */
    public String getNoteAttribute(Element element) {
        String xattribute = "";
        DefaultAttribute e = null;
        List list = element.attributes();
        for (int i = 0; i < list.size(); i++) {
            e = (DefaultAttribute) list.get(i);
            //System.out.println("name = " + e.getName() + ", value = " + e.getText());
            xattribute += " [name = " + e.getName() + ", value = " + e.getText() + "]";

            this.fillAll(element.getPath(), e.getName());
        }
        return xattribute;
    }

    private void fillAll(String path, String arr) {
        this.fillMap(doforcejob, path, arr, "/DEFTABLE/FOLDER/JOB/ON/DOFORCEJOB");
        this.fillMap(on, path, arr, "/DEFTABLE/FOLDER/JOB/ON");
        this.fillMap(doaction, path, arr, "/DEFTABLE/FOLDER/JOB/ON/DOACTION");
        this.fillMap(incond, path, arr, "/DEFTABLE/FOLDER/JOB/INCOND");
        this.fillMap(outcond, path, arr, "/DEFTABLE/FOLDER/JOB/OUTCOND");
        this.fillMap(shout, path, arr, "/DEFTABLE/FOLDER/JOB/SHOUT");
        this.fillMap(variable, path, arr, "/DEFTABLE/FOLDER/JOB/VARIABLE");
        this.fillMap(job, path, arr, "/DEFTABLE/FOLDER/JOB");
        this.fillMap(folder, path, arr, "/DEFTABLE/FOLDER");
    }

    private void fillMap(Map<String, Integer> target, String path, String k, String tag) {
        if (path.equals(tag)) {
            Integer num = target.get(k);
            target.put(k, num == null ? 1 : num + 1);
        }
    }

    /**
     * 递归遍历方法
     * <功能详细描述>
     *
     * @param element
     * @see [类、类#方法、类#成员]
     */
    public void getElementList(Element element) {
        // 整理节点类型及使用数量
//        Integer num = xpaths.get(element.getPath());
//        xpaths.put(element.getPath(), num == null? 1 : num + 1);


        String name = element.getName();
        // 如果是根节点，不需要做任何处理
        if (!("DEFTABLE".equals(name) || "FOLDER".equals(name))) {
            // 不论是否有子元素，先查看一下节点名
            //System.out.println("name:" + name);
            switch (name) {
                case "JOB":
                    ExcelBean bean = getAttFromJob(element);
                    beanList.add(bean);
            }
        }


        List elements = element.elements();
        // 没有子元素
        if (elements.isEmpty()) {
            String xpath = element.getPath();
            String value = element.getTextTrim();
            elemList.add(new Leaf(getNoteAttribute(element), xpath, value));
        } else {
            // 有子元素
            Iterator it = elements.iterator();
            while (it.hasNext()) {
                Element elem = (Element) it.next();
                String xpath = element.getPath();
                String value = element.getTextTrim();
                elemList.add(new Leaf(getNoteAttribute(element), xpath, value));
                // 递归遍历
                getElementList(elem);
            }
        }
    }

    public String getListString(List elemList) {
        StringBuffer sb = new StringBuffer();
        for (Iterator it = elemList.iterator(); it.hasNext(); ) {
            Leaf leaf = (Leaf) it.next();
            sb.append("xpath: " + leaf.getXpath()).append(", value: ").append(leaf.getValue());
            if (!"".equals(leaf.getXattribute())) {
                sb.append(", Attribute: ").append(leaf.getXattribute());
            }
            sb.append("\n");
        }
        return sb.toString();
    }
}
